ROOT_URL = "http://localhost:8080/swimpool/controller"
window.ROOT_URL = ROOT_URL

class User extends Backbone.Model
    urlRoot: ROOT_URL + "/users"
    # id
    # name
    # description
    # information
    # avatar

    url: () =>
        id = this.get("id")
        if id and (id >= 0)
            return @urlRoot + "/" + id
        else
            return @urlRoot

    avatarUrl: () ->
        this.url() + "/avatar"

    initialize: () ->
        @skills = new SkillCollection()
        @skills.url = () => this.url() + "/skills"

        @friends = new UserCollection()
        @friends.url = () => this.url() + "/friends"

        @feedbacks = new FeedbackCollection()
        @feedbacks.url = () => this.url() + "/feedbacks"

        this.set("role", null)
        this.on("change:id", @idChanged)

    copyFrom: (user) ->
        this.set("id", user.get("id"))
        this.set("name", user.get("name"))
        this.set("description", user.get("description"))
        this.set("information", user.get("information"))
        this.set("email", user.get("email"))

    idChanged: (id) =>
        @id = this.get("id")
        @skills.url = () => this.url() + "/skills"
        @friends.url = () => this.url() + "/friends"

    demote: (onSuccess, onError) =>
      url = "#{ROOT_URL}/admins/#{@id}"

      $.ajax
        type: "DELETE"
        contentType: "application/json"
        url: url
        dataType: "*/*"
        success: onSuccess
        error: handleErrorCodes(onError, onSuccess)

    promote: (onSuccess, onError) =>
      url = "#{ROOT_URL}/admins/#{@id}"

      $.ajax
        type: "PUT"
        contentType: "application/json"
        url: url
        dataType: "*/*"
        success: onSuccess
        error: handleErrorCodes(onError, onSuccess)

    isAdmin: () ->
        role = this.get("role")
        return (role == "Administrator") or (role == "SuperUser")

    isSuperUser: () ->
        return (this.get("role") == "SuperUser")

    isVisitor: () ->
        return (this.get("role") == null)

    addSkill: (skill, onSuccess, onError) ->
        sid = skill.get("id")
        url = "#{this.url()}/skills/#{sid}"

        $.ajax
            type: "PUT"
            url: url
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)

    deleteAvatar: (onSuccess, onError) ->
        url = this.url() + "/avatar"
        $.ajax
            type: "DELETE"
            url: url
            data: ""
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)

    register: (email, password, onSuccess, onError) ->
        url = "#{ROOT_URL}/users"
        this.set("email", email)
        $.ajax
            type: "POST"
            url: url
            data: JSON.stringify({ email: email, password: password})
            contentType: "application/json"
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)

    forcePassword: (password, onSuccess, onError) ->
        url = this.url() + "/password"
        $.ajax
            type: "PUT"
            url: url
            data: password
            contentType: "text/plain"
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)

class StaticUserFunctions
    resetViaEmail: (email, onSuccess, onError) ->
        url = "#{ROOT_URL}/self/reset/password?email=#{email}"
        $.ajax
            type: "PUT"
            url: url
            data: ""
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)

    resetViaUsername: (username, onSuccess, onError) ->
        url = "#{ROOT_URL}/self/reset/account?name=#{username}"
        $.ajax
            type: "PUT"
            url: url
            data: ""
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)

    activate: (id, onSuccess, onError) ->
        url = "#{ROOT_URL}/accounts/#{id}"
        $.ajax
            type: "PUT"
            url: url
            data: ""
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)

    login: (email, password, onSuccess, onError) ->
        url = "#{ROOT_URL}/login"
        credentials =
            email: email
            password: password

        $.ajax
            type: "POST"
            url: url
            data: JSON.stringify(credentials)
            contentType: "application/json"
            dataType: "text/plain"
            success: onSuccess
            error: (xhr) ->
                if (xhr.status == 200)
                    onSuccess(xhr.responseText)
                else
                    onError(xhr)


class UserCollection extends Backbone.Collection
    url: () ->
        ROOT_URL + "/users"

    model: User

class LoggedUser extends User
    urlRoot: ROOT_URL + "/self"

    url: () =>
        return @urlRoot

    initialize: () ->
        super

        @messages = new MessageCollection()
        @messages.url = ROOT_URL + "/self/messages"

        @requests = new FriendshipRequestCollection()
        @requests.url = ROOT_URL + "/self/requests"

    save: (attributes, options) ->
        putUrl = this.url()

        if attributes.name
            this.set("name", attributes.name)

        if attributes.description
            this.set("description", attributes.description)

        if attributes.information
            this.set("information", attributes.information)

        $.ajax
            type: "PUT"
            contentType: "application/json"
            data: JSON.stringify(attributes)
            url: putUrl
            dataType: "*/*"
            error: handleErrorCodes(options.error, options.success)
            success: options.success

    removeFriend: (friend, onSuccess, onError) ->
        id = friend.get("id")
        url = "#{ROOT_URL}/self/friends/#{id}"
        $.ajax
            type: "DELETE"
            url: url
            data: ""
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)

    uploadAvatar: (data, onSuccess, onError, onProgress) ->
        url = this.url() + "/avatar"
        $.ajax
            url: url
            type: "PUT"
            data: data
            xhr: () ->
                myXhr = $.ajaxSettings.xhr()
                if myXhr.upload
                    myXhr.upload.addEventListener('progress', onProgress, false)
                return myXhr
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)
            cache: false
            contentType: false
            processData: false

    logout: () ->
        this.set("id", -1)
        this.set("name", "Visitor")
        this.set("description", null)
        this.set("information", null)
        this.set("role", null)


class Skill extends Backbone.Model
    urlRoot: ROOT_URL + "/skills"
    # id
    # name
    # description

    propose: (onSuccess, onError) ->
        this.url = () -> "#{ROOT_URL}/skills/proposals"

        name = this.get("name")
        description = this.get("description")

        attributes =
            name: name
            description: description

        options =
            success: onSuccess
            error: onError

        this.save(attributes, options)

    approve: (onSuccess, onError) ->
        id = this.get("id")
        url = "#{ROOT_URL}/skills/proposals/#{id}?accepted=true"
        $.ajax
            type: "DELETE"
            url: url
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)

    decline: (onSuccess, onError) ->
        this.url = () -> "#{ROOT_URL}/skills/proposals"
        this.destroy()


class SkillCollection extends Backbone.Collection
    model: Skill

    getById: (id) ->
        match = this.where({id: Number(id)})

        if !match or match.length == 0
            return null

        return match[0]

class SkillDatabase extends SkillCollection
    constructor: () ->
        super
        @lastUpdate = 0
        @minUpdateInterval = 5000

    url: () ->
        ROOT_URL + "/skills"

    isEmpty: () ->
        this.length == 0


class Feedback extends Backbone.Model
    urlRoot: ROOT_URL + "/feedbacks"
    # author
    # skill
    # rating
    # text
    # creationDate

class FeedbackCollection extends Backbone.Collection
    model: Feedback


class Message extends Backbone.Model
    # sender
    # date
    # text
    sendToId: (id, onSuccess, onError) ->
        text = this.get("text")
        url = "#{ROOT_URL}/users/#{id}/messages"

        $.ajax
            type: "POST"
            contentType: "text/plain"
            dataType: "*/*"
            url: url
            data: text
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)

    sendTo: (user, onSuccess, onError) ->
        id = user.get("id")
        this.sendToId(id, onSuccess, onError)

class MessageCollection extends Backbone.Collection
    model: Message


class FriendshipRequest extends Backbone.Model
    # sender
    # date
    send: (onSuccess, onError) ->
        target = this.get("target")
        url = "#{target.url()}/requests"
        $.ajax
            type: "POST"
            url: url
            data: ""
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)

    accept: (onSuccess, onError) ->
        id = this.getId()
        url = "#{ROOT_URL}/self/requests/#{id}?accepted=true"
        $.ajax
            type: "DELETE"
            url: url
            dataType: "*/*"
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)

    decline: (onSuccess, onError) ->
        id = this.getId()
        url = "#{ROOT_URL}/self/requests/#{id}"
        $.ajax
            type: "DELETE"
            url: url
            dataType: "*/*"
            success: onSuccess
            error: handleErrorCodes(onError, onSuccess)

    getId: () ->
        sender = this.get("sender")

        if sender.get
            return sender.get("id")

        return sender.id

    getSenderName: () ->
        sender = this.get("sender")

        if sender.get
            return sender.get("name")

        return sender.name

class FriendshipRequestCollection extends Backbone.Collection
    model: FriendshipRequest


# Expose models outside
window.model =
    User: User
    Skill: Skill
    Feedback: Feedback
    Message: Message
    FriendshipRequest: FriendshipRequest
    LoggedUser: LoggedUser
    SkillDatabase: SkillDatabase

window.utils =
    User: new StaticUserFunctions()

window.collection =
    User: UserCollection
    Skill: SkillCollection
    Feedback: FeedbackCollection


# User whose profile is being viewed
window.targetUser = new User()

# Logged user
window.currentUser = new LoggedUser()

window.loadPersonalInfo = () ->
    window.currentUser.fetch
        success: () ->
            window.targetUser.copyFrom(window.currentUser)
            $("#homeLabel").text(currentUser.get("name"))

            if currentUser.isAdmin()
                $("#showProposals").show()
            else
                $("#showProposals").hide()
